#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <getopt.h>
#include <inttypes.h>

typedef struct {
    char *input_file;
    char *output_file;
    char *match_pattern;
    char *output_format;
    int skip_bytes;
    int output_length;
    FILE *out_stream;
} ProgramOptions;

typedef struct {
    unsigned char *pattern;
    int *is_wildcard;
    int length;
} MatchPattern;

ProgramOptions options = {0};
MatchPattern match_info = {0};

void print_help() {
    printf("Usage: hci_parser [options]\n"
           "Options:\n"
           "  -f <file>   指定输入的HCI文件\n"
           "  -w <file>   将结果写入文件,format被强行设置为bin\n"
           "  -p <format> 输出格式(string/hex/bin，默认hex)\n"
           "  -m <pattern> 匹配模式(十六进制，xx为通配符)\n"
           "  -s <num>    匹配后跳过的字节数\n"
           "  -l <num>    输出数据长度\n"
           "  -h          显示帮助信息\n"
           "示例: \n"
           "  hci_parser -f input.log -m \"001122xx3344\" -s 2 -l 4 -p hex -w result.txt\n");
}

int parse_hex_pattern(const char *input) {
    size_t len = strlen(input);
    if (len % 2 != 0) return -1;

    match_info.length = len / 2;
    match_info.pattern = malloc(match_info.length);
    match_info.is_wildcard = calloc(match_info.length, sizeof(int));

    for (size_t i = 0; i < len; i += 2) {
        if (input[i] == 'x' && input[i+1] == 'x') {
            match_info.pattern[i/2] = 0;
            match_info.is_wildcard[i/2] = 1;
        } else {
            char byte_str[3] = {input[i], input[i+1], '\0'};
            match_info.pattern[i/2] = (unsigned char)strtol(byte_str, NULL, 16);
        }
    }
    return 0;
}

int check_match(const unsigned char *data, int data_len) {
    if (data_len < match_info.length) return 0;
    //printf("%02x%02x%02x%02x%02x%02x\n",data[0],data[1],data[2],data[3],data[4],data[5]);
    for (int i = 0; i < match_info.length; i++) {
        if (!match_info.is_wildcard[i] && 
            data[i] != match_info.pattern[i]) {
            return 0;
        }
    }
    return 1;
}

void process_data(const unsigned char *data, int data_len) {
    if (!check_match(data, data_len)) return;

    int start_pos = match_info.length + options.skip_bytes;
    if (start_pos >= data_len) return;
    
    int output_len = options.output_length;
    if (start_pos + output_len > data_len) {
        output_len = data_len - start_pos;
    }

    const unsigned char *output_ptr = data + start_pos;
    
    if (strcmp(options.output_format, "string") == 0) {
        for (int i = 0; i < output_len; i++) {
            fputc(isprint(output_ptr[i]) ? output_ptr[i] : '.', options.out_stream);
        }
        fprintf(options.out_stream, "\n");
    } else if (strcmp(options.output_format, "hex") == 0) {
        fprintf(options.out_stream, "0x");
        for (int i = 0; i < output_len; i++) {
            fprintf(options.out_stream, "%02X", output_ptr[i]);
        }
        fprintf(options.out_stream, "\n");
    }else if (strcmp(options.output_format, "bin") == 0) {
		fwrite(output_ptr, sizeof(output_ptr[0]), output_len, options.out_stream);
	}
}

int process_file(FILE *file) {
    unsigned char header[16];
    if (fread(header, 1, 16, file) != 16 || memcmp(header, "btsnoop\0", 8) != 0) {
        fprintf(stderr, "无效的BTSnoop文件\n");
        return -1;
    }

    unsigned char packet[0xFFFF];
    while (!feof(file)) {
        unsigned char len_field[4];
        if (fread(len_field, 1, 4, file) != 4) break;
        
        uint32_t packet_len = (len_field[0] << 24) | 
                             (len_field[1] << 16) | 
                             (len_field[2] << 8)  | 
                              len_field[3];
        
        fseek(file, 20, SEEK_CUR); // 跳过包头
        if (fread(packet, 1, packet_len, file) != packet_len) break;
        process_data(packet + 1, packet_len - 1); //skip first byte(destition flag)
    }
    return 0;
}

int main(int argc, char **argv) {
    options.output_format = "hex";
    options.out_stream = stdout;

    int opt;
    while ((opt = getopt(argc, argv, "f:w:p:m:s:l:h")) != -1) {
        switch (opt) {
        case 'f': options.input_file = optarg; break;
        case 'w': options.output_file = optarg; break;
        case 'p': options.output_format = optarg; break;
        case 'm': options.match_pattern = optarg; break;
        case 's': options.skip_bytes = atoi(optarg); break;
        case 'l': options.output_length = atoi(optarg); break;
        case 'h': print_help(); return 0;
        default: print_help(); return 1;
        }
    }

    if (!options.input_file || !options.match_pattern) {
        print_help();
        return 1;
    }

    if (parse_hex_pattern(options.match_pattern) != 0) {
        fprintf(stderr, "无效的匹配模式\n");
        return 1;
    }

    if (options.output_file) {
        options.out_stream = fopen(options.output_file, "w");
        if (!options.out_stream) {
            perror("无法打开输出文件");
            return 1;
        }
		options.output_format = "bin";
    }

    FILE *file = fopen(options.input_file, "rb");
    if (!file) {
        perror("无法打开输入文件");
        return 1;
    }

    int ret = process_file(file);
    
    fclose(file);
    if (options.output_file) fclose(options.out_stream);
    free(match_info.pattern);
    free(match_info.is_wildcard);
    return ret;
}